package com.wltt.product.ahuthr.component;

import com.wltt.product.ahuthr.config.exception.BusinessException;
import com.wltt.product.ahuthr.constants.FlowConstant;
import com.wltt.product.ahuthr.enums.FlowRecordDealResultEnum;
import com.wltt.product.ahuthr.enums.FlowRecordStatusEnum;
import com.wltt.product.ahuthr.enums.FlowStatusEnum;
import com.wltt.product.ahuthr.holder.UserHolder;
import com.wltt.product.ahuthr.mapper.FlowMapper;
import com.wltt.product.ahuthr.mapper.FlowRecordMapper;
import com.wltt.product.ahuthr.mapper.SystemFlowNodeMapper;
import com.wltt.product.ahuthr.model.po.FlowPO;
import com.wltt.product.ahuthr.model.po.FlowRecordPO;
import com.wltt.product.ahuthr.model.po.SystemFlowNodePO;
import com.wltt.product.ahuthr.model.po.SystemFlowPO;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class FlowComponent {

    @Resource
    private FlowMapper flowMapper;

    @Resource
    private SystemFlowNodeMapper systemFlowNodeMapper;

    @Resource
    private FlowRecordMapper flowRecordMapper;

    /**
     * 开始流程
     * 注意调用该方法的外部方法需要开始事务
     *
     * @param systemFlowPO
     * @return
     */
    public FlowPO startFlow(SystemFlowPO systemFlowPO, Date startTime, String flowObz) {

        // 找到当前节点
        SystemFlowNodePO startNode = systemFlowNodeMapper.queryBySystemFlowIdAndNodeCode(systemFlowPO.getId(), FlowConstant.START);
        SystemFlowNodePO currentNode = systemFlowNodeMapper.queryById(startNode.getNextNodeId());

        // 1 插入流程
        FlowPO flowPO = new FlowPO();
        flowPO.setSystemFlowId(systemFlowPO.getId());
        flowPO.setFlowObz(String.valueOf(flowObz));
        flowPO.setSubmitDatetime(startTime);
        flowPO.setFlowStatus(FlowStatusEnum.ON_APPROVE.getCode());
        flowPO.setCurrentNodeId(currentNode.getNextNodeId());
        flowMapper.insertSelective(flowPO);


        // 2.2 插入流程节点
        FlowRecordPO flowRecordPO = new FlowRecordPO();
        flowRecordPO.setFlowId(flowPO.getId());
        flowRecordPO.setSystemNodeId(currentNode.getId());
        flowRecordPO.setUserId(UserHolder.getUserId());
        flowRecordPO.setRecordDate(startTime);
        flowRecordPO.setRecordStatus(FlowRecordStatusEnum.DEAL.getCode());
        flowRecordPO.setDealResult(FlowRecordDealResultEnum.PASS.getCode());
        flowRecordMapper.insertSelective(flowRecordPO);

        return flowPO;
    }

    /**
     * 审批流程
     * 注意调用该方法的外部方法需要开始事务
     *
     * @param flowId
     * @return 流程状态：100审批中；110已打回; 120已撤回； 200已完成；
     */
    public FlowStatusEnum auditFlow(Long flowId, Date dealTime, Integer dealResult, String rejectReason) {

        FlowPO flowPO = flowMapper.queryById(flowId);
        if (flowPO == null) {
            throw new BusinessException("无法找到该用户的审批流", HttpStatus.BAD_REQUEST);
        }
        if (FlowStatusEnum.ON_APPROVE.getCode() != flowPO.getFlowStatus()) {
            throw new BusinessException("流程状态发生变化", HttpStatus.BAD_REQUEST);
        }
        Long currentNodeId = flowPO.getCurrentNodeId();

        SystemFlowNodePO auditNode = systemFlowNodeMapper.queryById(currentNodeId);

        // 2.2 插入流程节点
        FlowRecordPO flowRecordPO = new FlowRecordPO();
        flowRecordPO.setFlowId(flowPO.getId());
        flowRecordPO.setSystemNodeId(auditNode.getId());
        flowRecordPO.setUserId(UserHolder.getUserId());
        flowRecordPO.setRecordDate(dealTime);
        flowRecordPO.setRecordStatus(FlowRecordStatusEnum.DEAL.getCode());
        flowRecordPO.setDealResult(dealResult);
        flowRecordPO.setRejectReason(rejectReason);
        flowRecordMapper.insertSelective(flowRecordPO);

        flowPO.setCurrentNodeId(auditNode.getNextNodeId());

        if (FlowRecordDealResultEnum.REJECT.getCode() == dealResult) {
            flowPO.setFlowStatus(FlowStatusEnum.REJECT.getCode());
            flowMapper.updateById(flowPO);
            return FlowStatusEnum.REJECT;
        }

        SystemFlowNodePO nextNode = systemFlowNodeMapper.queryById(auditNode.getNextNodeId());
        if (FlowConstant.END.equalsIgnoreCase(nextNode.getSystemNodeCode())) {
            flowPO.setFlowStatus(FlowStatusEnum.PASS.getCode());
            flowMapper.updateById(flowPO);
            return FlowStatusEnum.PASS;
        }

        flowMapper.updateById(flowPO);
        return FlowStatusEnum.ON_APPROVE;
    }

}
